﻿using System;
using System.Drawing;
using System.Net.Sockets;
using System.Net;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Threading;
using System.Linq;
using System.Diagnostics;

namespace RemoteImg
{
    public partial class Form1 : Form
    {
        private TcpClient client;
        private NetworkStream stream;

        public Form1()
        {
            InitializeComponent();
        }

        private double rec_fps;
        private DateTime rec_start_time;
        private int rec_frame_count;

        private double show_fps;
        private DateTime show_start_time;
        private int show_frame_count;
        private byte[] buffer;

        private async void 开始获取ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.StartButton.Enabled = false;
            this.IPTxt.Enabled = false;
            var serverPort = 5383;
            try
            {
                //先开启图像服务
                this.client = new TcpClient();
                // 将域名解析为 IP 地址
                var ipAdd = this.GetIPAddress(this.IPTxt.Text);

                await client.ConnectAsync(ipAdd, serverPort);
                this.stream = this.client.GetStream();
                new Thread(this.ShowImageMethod) { IsBackground = true }.Start();
                new Thread(this.ShowFrameMethod) { IsBackground = true }.Start();
                await Task.Run(this.LoadImageAsync);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"连接远程图像服务出现异常:{ex.Message}");
            }
            this.StartButton.Enabled = true;
            this.IPTxt.Enabled = true;
        }

        private IPAddress GetIPAddress(string text)
        {
            var addresses = Dns.GetHostAddresses(this.IPTxt.Text.Trim());
            foreach (var address in addresses)
            {
                if (address.ToString().Equals(text))
                    return address;
            }
            return addresses.FirstOrDefault();
        }

        private void ShowFrameMethod()
        {
           
            while (true)
            {
                try
                {
                    this.Invoke(new Action(() =>
                            {
                                this.Text = $"接收帧率->{this.rec_fps:f2} FPS, 显示帧率->{this.show_fps:f2} FPS";
                            }));
                }
                catch (Exception)
                {

                }
                Thread.Sleep(200);
            }
        }

        private void ShowImageMethod()
        {
            this.show_start_time = DateTime.Now;
            while (true)
            {
                if (this.buffer == null)
                {
                    Thread.Sleep(1);
                    continue;
                }

                try
                {
                    var currentImg = this.DecompressDeflateAndLoadPng(this.buffer);
                    this.Invoke(new Action(() =>
                           {
                               this.pictureBox1.Image?.Dispose();
                               this.pictureBox1.Image = currentImg;
                           }));
                }
                catch (Exception)
                {

                }
                finally
                {
                    this.UpdateShowFrame();
                }

                this.buffer = null;
            }
        }

        private async Task LoadImageAsync()
        {
            this.rec_start_time = DateTime.Now;
            while (true)
            {
                // 接收数据长度（假设长度用 4 字节的整数表示）
                byte[] lengthBuffer = await this.ReadAsync(stream, 4);

                if (lengthBuffer.Length != 4)
                {
                    Console.WriteLine("接收数据长度时出错。");
                    stream.Close();
                    client.Close();
                    return;
                }
                int dataLength = BitConverter.ToInt32(lengthBuffer, 0);

                // 处理接收到的数据，这里简单保存为文件
                try
                {
                    var dataBuffer = await this.ReadAsync(stream, dataLength);

                    //更新帧率
                    //this.UpdateRecFrame(ref this.rec_frame_count, ref this.rec_fps, ref this.rec_start_time);
                    this.UpdateRecFrame();
                    if (this.buffer != null)
                        continue;

                    this.buffer = dataBuffer;
                }
                catch
                {

                }
            }
        }

        private Bitmap DecompressDeflateAndLoadPng(byte[] compressedData)
        {
            using (MemoryStream compressedMs = new MemoryStream(compressedData))
                return new Bitmap(compressedMs);
        }


        private async Task<byte[]> ReadAsync(NetworkStream stream, int dataLength)
        {
            // 用于存储接收到的数据
            byte[] dataBuffer = new byte[dataLength];
            int totalBytesRead = 0;
            int bytesRead = 0;
            // 循环接收数据，直到接收到指定长度的数据
            while (true)
            {
                bytesRead = await stream.ReadAsync(dataBuffer, totalBytesRead, dataLength - totalBytesRead);
                if (bytesRead == 0)
                {
                    Console.WriteLine("连接意外关闭。");
                    break;
                }
                totalBytesRead += bytesRead;
                if (totalBytesRead == dataLength)
                    break;
            }
            return dataBuffer;
        }


        private void UpdateRecFrame()
        {
            this.rec_frame_count++;
            TimeSpan elapsed_time = DateTime.Now - this.rec_start_time;
            if (elapsed_time.TotalSeconds > 0)
            {
                this.rec_fps = this.rec_frame_count / elapsed_time.TotalSeconds;
            }
            if (elapsed_time.TotalSeconds > 1)
            {
                this.rec_frame_count = 0;
                this.rec_start_time = DateTime.Now;
            }
        }

        private void UpdateShowFrame()
        {
            this.show_frame_count++;
            TimeSpan elapsed_time = DateTime.Now - this.show_start_time;
            if (elapsed_time.TotalSeconds > 0)
            {
                this.show_fps = this.show_frame_count / elapsed_time.TotalSeconds;
            }
            if (elapsed_time.TotalSeconds > 1)
            {
                this.show_frame_count = 0;
                this.show_start_time = DateTime.Now;
            }
        }

        private void IPTxt_Click(object sender, EventArgs e)
        {

        }
    }
}
